// no 4 and 14
#include "Fraction.h"
#include <iostream>
#include <stdio.h>
#include <math.h>
#define SIZE 5
Fraction::Fraction()
{
	this -> numerator = 1;
	this -> denominator = 1;
}
Fraction::Fraction(int n, int d)
{
	this -> numerator = n;
	this -> denominator = d;
}
Fraction::Fraction(const Fraction *f)
{
	this -> numerator = f -> numerator;
	this -> denominator = f -> denominator;
}
Fraction::Fraction(const Fraction &f)
{
	this -> numerator = f.numerator;
	this -> denominator = f.denominator;
}
Fraction::~Fraction()
{
}
int Fraction::getNum(void) const
{
	return this -> numerator;
}
int Fraction::getDen(void) const
{
	return this -> denominator;
}
void Fraction::setNum(int num)
{
	this -> numerator = num;
}
void Fraction::setDen(int den)
{
	this -> denominator = den;
}
Fraction Fraction::operator * (const Fraction &f)
{
	int num = this -> numerator * f.numerator;
	int den = this -> denominator * f.denominator;
	return Fraction(num, den);
}
Fraction Fraction::operator * (int nr)
{
	int num = this -> numerator * nr;
	return Fraction(num, this -> denominator);
}
Fraction operator * (int nr, const Fraction &f)
{
	int num = nr * f.numerator;
	return Fraction(num, f.denominator);
}
void Fraction::Print(void) const
{
	printf("%d/%d ", this -> numerator, this -> denominator);
}
Fraction Fraction::operator / (const Fraction &f)
{
	int num = this -> numerator * f.denominator;
	int den = this -> denominator * f.numerator;
	return Fraction(num, den);
}
Fraction Fraction::operator / (int nr)
{
	int den = this -> denominator * nr;
	return Fraction(this -> numerator, den);
}
Fraction operator / (int nr, const Fraction &f)
{
	int num = nr * f.denominator;
	return Fraction(num, f.numerator);
}
Fraction Fraction::operator ^ (int power)
{
	int num = pow(this -> numerator, power);
	int den = pow(this -> denominator, power);
	return Fraction(num, den);
}
Fraction Fraction::operator + (const Fraction &f)
{
	int num = f.denominator * this -> numerator + this -> denominator * f.numerator;
	int den = this -> denominator * f.denominator;
	return Fraction(num, den);
}
Fraction Fraction::operator + (int nr)
{
	return Fraction(this -> numerator + this -> denominator * nr, this -> denominator);
}
Fraction operator + (int nr, const Fraction &f)
{
	return Fraction(f.denominator * nr + f.numerator, f.denominator);
}
Fraction Fraction::operator - (const Fraction &f)
{
	int num = f.denominator * this -> numerator - this -> denominator * f.numerator;
	int den = this -> denominator * f.denominator;
	return Fraction(num, den);
}
Fraction Fraction::operator - (int nr)
{
	return Fraction(this -> numerator - this -> denominator * nr, this -> denominator);
}
Fraction operator - (int nr, const Fraction &f)
{
	return Fraction(f.denominator * nr - f.numerator, f.denominator);
}
Fraction Sum(Fraction F[], int nr)
{
	Fraction result = F[0];
	for (int i = 1; i < nr; ++i)
		result = result + F[i];
	return result;
}
int Gcd(int x, int y)
{
	int g;
	for (int i = 1; i <= x; ++i)
		if (x % i == 0 && y % i == 0)
			g = i;
	return g;
}
void Fraction::Reduce(void)
{
	int g = Gcd(this -> numerator, this -> denominator);
	if (g > 1)
		while (this -> numerator >= g && this -> numerator % g == 0 && this -> denominator >= g && this -> denominator % g == 0)
		{
			this -> numerator /= g;
			this -> denominator /= g;
		}
	else
		printf("The fraction is already irreductible.");
}
void Sort(Fraction F[])
{
	int k, aux1, aux2;
	for (int i = 0; i < SIZE - 1; ++i)
	{
		k = i;
        for (int j = i + 1; j < SIZE; ++j)
			if (F[k].numerator / F[k].denominator > F[j].numerator / F[j].denominator)
				k = j;
        if (k != i)
		{
			aux1 = F[k].numerator;
			aux2 = F[k].denominator;
			F[k].numerator = F[i].numerator;
			F[k].denominator = F[i].denominator;
            F[i].numerator = aux1;
            F[i].denominator = aux2;
		}
	}
}
Fraction BigSub(Fraction F[])
{
	Fraction tmp;
	int i;
	for (i = 0; i < SIZE; ++i)
		if (F[i].numerator < F[i].denominator)
		{
			tmp = Fraction(F[i]);
			break;
		}
	for (int j = i + 1; j < SIZE; ++j)
		if (F[j].numerator < F[j].denominator && tmp.numerator / tmp.denominator < F[j].numerator / F[j].denominator)
			tmp = Fraction(F[j]);
	if (tmp.numerator == 1 && tmp.denominator == 1)
		printf("The are no subunitary fractions.");
	return tmp;
}
Fraction SmallSup(Fraction F[])
{
	Fraction tmp;
	int i;
	for (i = 0; i < SIZE; ++i)
		if (F[i].numerator > F[i].denominator)
		{
			tmp = Fraction(F[i]);
			break;
		}
	for (int j = i + 1; j < SIZE; ++j)
		if (F[j].numerator > F[j].denominator && tmp.numerator / tmp.denominator > F[j].numerator / F[j].denominator)
			tmp = Fraction(F[j]);
	if (tmp.numerator == 1 && tmp.denominator == 1)
		printf("The are no supraunitary fractions.");
	return tmp;
}
using namespace std;
int main()	
{
	Fraction F[SIZE];
	int v1[SIZE] = {12, 16, 20, 18, 12}, v2[SIZE] = {6, 8, 10, 12, 24};
	for (int i = 0; i < SIZE; ++i)
	{
		Fraction tmp = Fraction(v1[i], v2[i]);
		F[i] = Fraction(tmp);
		tmp.~Fraction();
	}
	for (int i = 0; i < SIZE; ++i)
	{
		F[i].Reduce();
		F[i].Print();
	}
	Sort(F);
	Fraction s = Sum(F, SIZE);
	s.Reduce();
	printf("\nSum = ");
	s.Print();
	printf("\n");
	for (int i = 0; i < SIZE; ++i)
		F[i].Print();
	cout << "\n";
	Fraction BS = BigSub(F);
	BS.Print();
	Fraction SS = SmallSup(F);
	SS.Print();
	return 0;
}